'use strict';

// 1. 导入 sequelize 模块和 DataTypes 内置数据类型
// sequelize模块，相当于js代码与数据库之间的一个工具，通过这个工具将js代码映射成数据库中的表
// DataTypes内置数据类型，在模型（模型是 Sequelize 的本质. 模型是代表数据库中表的抽象）中定义的每一列都必须具有数据类型. Sequelize 提供很多内置数据类型. 要访问内置数据类型,必须导入 DataTypes
const { Sequelize, DataTypes } = require('sequelize');

// 2. 导入数据库配置文件
const { database, username, password, host, dialect } = require('./config');

// 3. 实例化 sequelize 对象（相当于创建数据库）
// 四个参数，第一个为指定的数据库，第二个为登录数据库的用户名，第三个为登录数据库的密码，第四个为一个对象，对象里为数据库服务器所在IP地址和所使用的数据库语言
let sequelize = new Sequelize(database, username, password, {
    host: host,
    dialect: dialect
});

// 4. 编写函数，包装模型的定义内容
function defineModels(modelName, attrs) {
    // 所有的属性，包括原先定义好的和外部传进来的
    let prop = {}

    // 模型的 ID 列
    prop.id = {
        type: DataTypes.INTEGER, // int 类型
        primaryKey: true, // 主键
        autoIncrement: true // 自增
    }

    // 循环遍历外部传入的模型的属性
    for (let item in attrs) {
        prop[item] = attrs[item];
    }

    // 模型的创建时间
    prop.createAt = {
        type: DataTypes.DATE, // 日期类型
        allowNull: false // 不允许为空
    }

    // 模型的更新时间
    prop.updateAt = {
        type: DataTypes.DATE, // 日期类型
        allowNull: false
    }

    // 模型的备注
    prop.remarks = {
        type: DataTypes.STRING, // 字符串类型
        allowNull: true // 允许为空
    }

    // 5. 利用sequelize实例定义模型（相当于创建数据库中的表）
    // modelName 为模型名，也就是数据库表名；prop 为模型的属性，也就是数据库中的各列
    let modelObj = sequelize.define(modelName, prop, {
        // 强制表名与模型名一致
        tableName: modelName,
        // 不自动创建时间戳 createAt 和 updateAt
        timestamps: false,
        // 钩子函数（生命周期钩子）
        hooks: {
            // 在插入或更新数据之前执行的操作
            // 也就是在插入或更新数据之前，先触发这个钩子函数，给模型中的createAt和updateAt赋值
            beforeValidate: function (modelObj) {
                console.log(modelObj);
                // 获取当前时间
                let nowTime = Date.now();
                // 如果模型对象是一条新的记录，就代表是插入新数据
                if (modelObj.isNewRecord) {
                    // 模型的创建时间
                    modelObj.createAt = nowTime;
                    // 模型的更新时间
                    modelObj.updateAt = nowTime;
                } else {
                    // 更新数据
                    modelObj.updateAt = nowTime;
                }
            }
        }
    });
    return modelObj;
}

// 6. 创建一个对象，对象里包含sequelize实例、DateTypes内置数据类型、defineModels定义模型
let obj = {
    sequelize,
    DataTypes,
    defineModels
}

// 7. 暴露出去
module.exports = obj;

